package cn.wizzer.app.task.modules.services.impl;

import cn.wizzer.app.sys.modules.models.SysTask;
import cn.wizzer.app.sys.modules.services.SysTaskService;
import cn.wizzer.app.task.modules.services.TaskPlatformService;
import cn.wizzer.framework.util.JSONUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSONObject;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.integration.quartz.QuartzJob;
import org.nutz.integration.quartz.QuartzManager;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.quartz.*;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.JobExecutionContextImpl;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.quartz.impl.triggers.SimpleTriggerImpl;
import org.quartz.spi.TriggerFiredBundle;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Created by wizzer on 2018/3/19.
 */
@IocBean
@Service(interfaceClass = TaskPlatformService.class)
public class TaskPlatformServiceImpl implements TaskPlatformService {

    private static final Log log = Logs.get();

    @Inject
    private QuartzManager quartzManager;

    @Inject("refer:$ioc")
    private Ioc ioc;


    @Inject
    @Reference
    private SysTaskService sysTaskService;


    /**
     * 判断任务是否存在
     *
     * @param jobName
     * @param jobGroup
     * @return
     */
    public boolean isExist(String jobName, String jobGroup) {
        return quartzManager.exist(new JobKey(jobName, jobGroup));
    }

    /**
     * 添加新任务
     *
     * @param jobName
     * @param jobGroup
     * @param className
     * @param cron
     * @param comment
     * @param dataMap
     */
    public void add(String jobName, String jobGroup, String className, String cron, String comment, String dataMap) {
        QuartzJob qj = new QuartzJob();
        qj.setJobName(jobName);
        qj.setJobGroup(jobGroup);
        qj.setClassName(className);
        qj.setCron(cron);
        qj.setComment(comment);
        qj.setDataMap(dataMap);
        quartzManager.add(qj);
    }

    /**
     * 删除任务
     *
     * @param jobName
     * @param jobGroup
     * @return
     */
    public boolean delete(String jobName, String jobGroup) {
        QuartzJob qj = new QuartzJob();
        qj.setJobName(jobName);
        qj.setJobGroup(jobGroup);
        return quartzManager.delete(qj);
    }

    /**
     * 清除任务
     */
    public void clear() {
        quartzManager.clear();
    }

    /**
     * 获取cron表达式最近执行时间
     *
     * @param cronExpression
     * @return
     */
    public List<String> getCronExeTimes(String cronExpression) throws Exception {
        List<String> list = new ArrayList<>();
        CronTriggerImpl cronTriggerImpl = new CronTriggerImpl();
        cronTriggerImpl.setCronExpression(cronExpression);
        Calendar calendar = Calendar.getInstance();
        Date now = calendar.getTime();
        calendar.add(2, 1);
        List<Date> dates = TriggerUtils.computeFireTimesBetween(cronTriggerImpl, null, now, calendar.getTime());
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (int i = 0; i < dates.size() && i <= 4; ++i) {
            list.add(dateFormat.format((Date) dates.get(i)));
        }
        return list;
    }

    /**
     * 手动执行一次任务
     */
    @Override
    public void manualExecute(SysTask sysTask) {
        String jobClassName = sysTask.getJobClass();
        String jobParam = sysTask.getData();
        // 根据前端传来执行类名。调用指定对象的方法。
        JobDetailImpl detail = new JobDetailImpl();
        // set 定时任务的id
        detail.setKey(JobKey.jobKey(sysTask.getId()));
        TriggerFiredBundle firedBundle = new TriggerFiredBundle(detail, new SimpleTriggerImpl(), null, false, null, null, null, null);
        JobExecutionContextImpl jobExecutionContext = new JobExecutionContextImpl(null, firedBundle, null);
        if (Strings.isNotBlank(jobParam)) {
            JSONObject map = JSONUtil.parseToJSON(jobParam);
            JobDataMap jobDataMap = new JobDataMap(map);
            detail.setJobDataMap(jobDataMap);
        }
        try {
            Job job = (Job) ioc.get(Class.forName(jobClassName));
            job.execute(jobExecutionContext);
        } catch (ClassNotFoundException | JobExecutionException e) {
            log.error(e.getMessage());
        }
    }
}
